package com.cheer.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheer.dao.ReferenceFileDao;
import com.cheer.entity.Applicant;
import com.cheer.entity.ReferenceEntity;
import com.cheer.entity.ReferenceFileEntity;
import com.cheer.enums.ReferenceFileEnum;
import com.cheer.exception.ServiceException;
import com.cheer.param.ReferenceFileDownParam;
import com.cheer.properties.DocumentProperties;
import com.cheer.service.ApplicantService;
import com.cheer.service.ReferenceFileService;
import com.cheer.service.ReferenceService;
import com.cheer.util.FileUtil;
import com.cheer.vo.DocumentVO;
import com.cheer.vo.ReferenceDetailVO;
import com.cheer.vo.ReferenceListVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;


@Service("referenceFileService")
public class ReferenceFileServiceImpl extends ServiceImpl<ReferenceFileDao, ReferenceFileEntity> implements ReferenceFileService {

    @Autowired
    private DocumentProperties documentProperties;

    @Autowired
    private ReferenceFileDao referenceFileDao;

    @Autowired
    private ReferenceService referenceService;

    @Autowired
    private ApplicantService applicantService;

    @Value("${document.temporary}")
    private String temporaryPath;

    @Value("${document.path}")
    private String path;

    @Value("${document.url}")
    private String url;



    @Override
    public DocumentVO upload(Long accountId, MultipartFile file, Integer fileType) throws IOException {
        // 文件类型的判断
        ReferenceFileEnum type = ReferenceFileEnum.getType(fileType);
        if(type == null){
            throw new ServiceException("请上传指定文件类型！");
        }
        Boolean standard = ReferenceFileEnum.isStandard(type, cn.hutool.core.io.FileUtil.extName(file.getOriginalFilename()));
        if(standard == false){
            throw new ServiceException("请上传指定文件类型！");
        }
        if (file == null) {
            throw new ServiceException("上传的文件无效");
        }
        Boolean overSize = type.isOverSize(file.getSize());
        if(overSize == true){
            throw new ServiceException("上传文件已超过指定大小");
        }
        // 存储文件
        String fileName = file.getOriginalFilename();
        String fileUrl = File.separator + accountId + File.separator
                + "reference" + File.separator + fileType
                + File.separator + UUID.randomUUID() + File.separator + fileName;

        FileUtil.saveFile(file, documentProperties.getPath() + fileUrl);
        // 返回数据处理
        return DocumentVO.build(fileName, fileUrl, documentProperties.getUrl());
    }

    @Override
    public void batchSave(List<ReferenceFileEntity> list, Long id) {

        referenceFileDao.removeByReferenceId(id);
        saveBatch(list);
    }

    @Override
    public void setVO(ReferenceListVO referenceListVO) {

        Long referenceId = referenceListVO.getId();
        List<ReferenceFileEntity> referenceFiles = referenceFileDao.selectByReferenceId(referenceId);
        // 推荐表和事迹
        if(CollectionUtil.isEmpty(referenceFiles)){
            return;
        }
        referenceListVO.setRecommend(DocumentVO.build(getFileUrlByType(referenceFiles, ReferenceFileEnum.RECOMMEND), documentProperties.getUrl()));
        referenceListVO.setStory(DocumentVO.build(getFileUrlByType(referenceFiles, ReferenceFileEnum.STORY), documentProperties.getUrl()));
        // 佐证图片
        Map<Integer, List<ReferenceFileEntity>> typeMapFiles = referenceFiles.stream().collect(Collectors.groupingBy(ReferenceFileEntity::getFileType));
        List<ReferenceFileEntity> list = typeMapFiles.get(ReferenceFileEnum.EVIDENCE.getCode());
        if(CollectionUtil.isNotEmpty(list)){
            List<String> evidences = list.stream().map(ReferenceFileEntity::getFileUrl).collect(Collectors.toList());
            List<DocumentVO> documentVOs = new ArrayList<>();
            for (String evidence : evidences) {
                documentVOs.add(DocumentVO.build(evidence, documentProperties.getUrl()));
            }
            referenceListVO.setEvidences(documentVOs);
        }
    }

    @Override
    public String down(ReferenceFileDownParam referenceFileDownParam) {

        String zipName = RandomUtil.randomString(12);
        String tempPath = temporaryPath + File.separator + zipName;
        List<Long> referenceIds = referenceFileDownParam.getIds();

        List<Long> fileTypes = referenceFileDownParam.getFileTypes();
        if(CollectionUtil.isEmpty(fileTypes)){
            throw new ServiceException("下载文件类型不能为空！");
        }
        for (int i = 0; i < referenceIds.size(); i++) {
            Long referenceId = referenceIds.get(i);
            ReferenceEntity referenceEntity = referenceService.getById(referenceId);
            Long applicantId = referenceEntity.getApplicantId();
            Applicant applicant = applicantService.getById(applicantId);

            String applicantName = applicant.getApplicantName();
            // 集体名称作为文件夹
            String target = tempPath + File.separator + applicantName + File.separator;
            List<ReferenceFileEntity> referenceFiles = referenceFileDao.selectByReferenceId(referenceId);

            if(fileTypes.contains(Long.valueOf(ReferenceFileEnum.RECOMMEND.getCode()))){
                // 推荐表
                copyFile(target, referenceFiles, ReferenceFileEnum.RECOMMEND);
            }
            if(fileTypes.contains(Long.valueOf(ReferenceFileEnum.STORY.getCode()))){
                // 事迹材料
                copyFile(target, referenceFiles, ReferenceFileEnum.STORY);
            }
            // 作证图片
            if(fileTypes.contains(Long.valueOf(ReferenceFileEnum.EVIDENCE.getCode()))){
                Map<Integer, List<ReferenceFileEntity>> typeMapFiles = referenceFiles.stream().collect(Collectors.groupingBy(ReferenceFileEntity::getFileType));
                List<ReferenceFileEntity> list = typeMapFiles.get(ReferenceFileEnum.EVIDENCE.getCode());
                List<String> evidences = list.stream().map(ReferenceFileEntity::getFileUrl).collect(Collectors.toList());
                // 转移文件
                for (int j = 0; j < evidences.size(); j++) {
                    String evidenceFile = evidences.get(j);
                    copyFileToTarget(target, ReferenceFileEnum.EVIDENCE, evidenceFile);
                }
            }

        }
        File zip = ZipUtil.zip(tempPath);
        return url + File.separator+ "temporary" + File.separator + zip.getName();
    }

    @Override
    public void preview(HttpServletResponse response, Long id) {

            ReferenceEntity referenceEntity = referenceService.getById(id);
            if(referenceEntity == null){
                throw new ServiceException("未查询到当前记录");
            }
            ReferenceListVO referenceListVO = new ReferenceListVO();
            BeanUtil.copyProperties(referenceEntity, referenceListVO);
            // 资料信息
            setVO(referenceListVO);
            ReferenceDetailVO referenceDetailVO = new ReferenceDetailVO();
            BeanUtil.copyProperties(referenceListVO, referenceDetailVO);
            List<DocumentVO> evidences = referenceListVO.getEvidences();
            List<String> links = evidences.stream().map(DocumentVO::getLink).collect(Collectors.toList());
            referenceDetailVO.setEvidenceLinks(links);
            String pdfLink = documentProperties.getPath()+referenceDetailVO.getRecommend().getLink();
            File file = new File(pdfLink);

            if (file.exists()){
                byte[] data = null;
                try {
                    FileInputStream input = new FileInputStream(file);
                    data = new byte[input.available()];
                    input.read(data);
                    response.getOutputStream().write(data);
                    input.close();
                } catch (Exception e) {
                    System.out.println(e);
                }
            }else{
                return;
            }

    }

    @Override
    public void uploadRecommend(String fileUrl, Long id) {

        ReferenceEntity referenceEntity = referenceService.getById(id);
        if(referenceEntity == null){
            throw new ServiceException("未查询到要修改的记录");
        }
        List<ReferenceFileEntity> list = referenceFileDao.selectByReferenceId(id);

        Map<Integer, List<ReferenceFileEntity>> mapByTypes = list.stream().collect(Collectors.groupingBy(ReferenceFileEntity::getFileType));
        ReferenceFileEntity recommend  = mapByTypes.get(ReferenceFileEnum.RECOMMEND.getCode()).get(0);
        recommend.setFileUrl(fileUrl);
        updateById(recommend);
    }

    private void copyFile(String target, List<ReferenceFileEntity> referenceFiles, ReferenceFileEnum fileEnum) {

        String recommendFile = getFileUrlByType(referenceFiles, fileEnum);
        copyFileToTarget(target, fileEnum, recommendFile);
    }

    private void copyFileToTarget(String target, ReferenceFileEnum fileEnum, String recommendFile) {
        String recommendFileName = cn.hutool.core.io.FileUtil.getName(recommendFile);
        cn.hutool.core.io.FileUtil.copy(path + recommendFile, target + fileEnum.getMessage()+ File.separator +recommendFileName, true);
    }

    private String getFileUrlByType(List<ReferenceFileEntity> referenceFiles, ReferenceFileEnum referenceFileEnum) {
        Map<Integer, List<ReferenceFileEntity>> typeMapFiles = referenceFiles.stream().collect(Collectors.groupingBy(ReferenceFileEntity::getFileType));
        List<ReferenceFileEntity> list = typeMapFiles.get(referenceFileEnum.getCode());

        if(CollectionUtil.isNotEmpty(list)){

            return list.get(0).getFileUrl();
        }
        return null;
    }


}